﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using QFramework;

namespace Gp.Scripts.Core
{
    public class GlobalSaveEvent
    {
        private ES3File _saveFile;

        public GlobalSaveEvent(ES3File saveFile)
        {
            _saveFile = saveFile;
        }

        public void Append(string key, object value)
        {
            _saveFile.Save(key, value);
        }
    }


    public class GlobalLoadEvent { }

    public class SaveFile
    {
        public void GetKey() {}
        public void SetKey(string key, object value) {}
    }


    [AutoLoad]
    public class SaveManager : BaseGameManager
    {
        public StorageModel Model => this.GetModel<StorageModel>();

        public string CurSaveFile
        {
            get => Model.CurFileName;
            set => Model.CurFileName = value;
        }

        private const string SceneSaveKey = "openning_scenes";
        private const string SaveFilePrefix = "save_";
        public ES3Settings SaveSettings => Model.Settings;
        
        protected override void OnInit() { }

        public void SaveGame()
        {
            const string savePath = ConstApplication.SAVE_PATH;
            string       oldFile  = savePath + CurSaveFile;
            string       newFile  = savePath + SaveFilePrefix + (GetSaveFiles().Length + 1);

            // 先将当前文件复制至新文件
            if (ES3.FileExists(oldFile, SaveSettings))
            {
                ES3.CopyFile(oldFile, newFile, SaveSettings, SaveSettings);
            }

            ES3File file = new ES3File(newFile, SaveSettings, false);
            foreach (var (key, value) in MainArchitecture.Interface.PersistentModels)
            {
                file.Save(key, value.OnSave());
            }
            
            this.SendEvent(new GlobalSaveEvent(file));
            
            // 存入当前开启的场景
            var scenes = SceneManageSystem.OpeningScenes();
            file.Save(SceneSaveKey, scenes);
            file.Sync();

            // 更改当前存档文件名
            CurSaveFile = newFile;
        }


        public void LoadGame(string saveFile)
        {
            CurSaveFile = saveFile;
            var filePath = ConstApplication.SAVE_PATH + saveFile;

            ES3File file = new ES3File(filePath, Model.Settings);

            var scenes = file.Load<List<string>>(SceneSaveKey);
            MainArchitecture.Interface.SendEvent<GlobalLoadEvent>();


            SceneManageSystem.LoadScenes(scenes.ToArray(), () =>
            {
                foreach (var (key, value) in MainArchitecture.Interface.PersistentModels)
                {
                    if (file.KeyExists(key))
                    {
                        value.OnLoad(file.Load<ISerializedModel>(key));
                    }
                }

                file.Clear();
            });
        }


        // public T LossyLoad<T>(string saveKey)
        // {
        //     return ES3.Load<T>(saveKey, ConstApplication.SAVE_PATH + CurSaveFile, SaveSettings);
        // }


        public string[] GetSaveFiles()
        {
            try
            {
                return ES3.GetFiles(ConstApplication.SAVE_PATH, SaveSettings).Where(x => !x.Contains(".meta"))
                    .ToArray();
            }
            catch (DirectoryNotFoundException e)
            {
                return Array.Empty<string>();
            }
        }

        public string GetSaveFileNameByIndex(int index)
        {
            return string.Empty;
        }
    }
}